Function.RegisterNamespace("System.Script.Attributes");

System.Script.Attributes.AttributeParser=function(){
    var _attributeRegEx=/(^|.\n?\s*)(((\[[^\]]*\])((\s*\/\/(.*)\n)|[ \r\t\v]*\n)+\s*)+)((var )?\s*[$_A-Za-z][$_A-Za-z0-9\.]*\s*=)?(\s*function\s*)(\s+([^(\s]+))?\s*\(/g;
//     var _attributeRegEx=/(^|.\n?\s*)(((\[[^\]]*\])((\s*\/\/(.*)\n)|(\s*\/\*(?!\*\/)\*\/)|[ \r\t\v]*\n)+\s*)+)((var )?\s*[$_A-Za-z][$_A-Za-z0-9\.]*\s*=)?(\s*function\s*)(\s+([^(\s]+))?\s*\(/g;

    // Public methods
    this.Parse=function(source){
        if(!source)return source;
        var parsedScript=parseFunctions(source.toString());
        return parsedScript;
    };
    
    // Private methods
    function parseFunctions(source){
        return source.replace(_attributeRegEx,decorationBuilder);
    }
    
    function decorationBuilder(fullMatch,leadingSpace,attributeClusters,attributeCluster,attribute,commentOrWhitespace,comment,commentText,variableAssignment,variableTag,functionTag,functionSpace,functionName,stringPosition,sourceString){
//    function decorationBuilder(fullMatch,leadingSpace,attributeClusters,attributeCluster,attribute,commentOrWhitespace,comment,commentText,blockComment,negativeLookAhead,variableAssignment,variableTag,functionTag,functionSpace,functionName,stringPosition,sourceString){
        if(fullMatch.toString().indexOf('=')==0)return fullMatch;
        var format="{0}{1}{2}new System.Script.Attributes.DecoratedFunction({3},\"{4}\",{5});{6}function {3}(";
        var name=functionName||(variableAssignment?variableAssignment.replace(/\bvar |\bthis.|=/g,''):getAnonymousName());
        var safeName=name.split('.').join('_');
        return String.Format(format,    
            leadingSpace||'',
            variableAssignment||'var ',
            !functionName&&variableAssignment?'':name+'=',
            safeName,
            name,
            String.TrimEnd(attributeClusters.replace(/\]\s*(,?)\s*(\[|$)/g,'],$2'),','),
            (leadingSpace||'').replace(/^[^\s]*/g,'')
        );
    }
    
    function getAnonymousName(){
        return 'anonymous_'+(new Date().getTime()+Math.round(Math.random()*100000));
    }
};